import os.path
import json
from abc import ABCMeta, abstractmethod


import constants
from SQLOperation.PatientSQLOperation import PatientSQLOperation


def changeProjectFile(patientId, topKey, method, key, value):
    """
    topKey: patientInformation
        insert: key, value(string)
        delete: key
        update: key, value(string)
        select: key (return a string)

    topKey: stlFiles
        insert: value(json dict)
        delete: index(int)
        update: index(int), value(json dict)(only need value you want to change)
        select: index(int) (return a json dict)

    topKey: points
        insert: value(json dict)
        delete: index(int)
        update: index(int), value(json dict)
        select: index(int) (return a json dict)

    topKey: information
        insert: key, value(json list)
        delete: key
        update: key, value(json list)
        select: key (return a json list)

    topKey: events
        insert: value(json dict)
        delete: can not delete
        update: can not update
        select: index (return a json dict)
    """
    patientId=str(patientId)
    if not PatientSQLOperation.searchById(patientId):
        return "patient not exist"
    else:
        if topKey in constants.jsonDictKeys:
            jsonDictFile = JsonDictFile(patientId, topKey)
            result = jsonDictFile.exec(method, key, value)
            return result
        elif topKey in constants.jsonListKeys:
            jsonListFile = JsonListFile(patientId, topKey)
            result = jsonListFile.exec(method, key, value)
            return result


class JsonFileInterface:
    __metaclass__ = ABCMeta

    @abstractmethod
    def insert(self, key, value):
        pass

    @abstractmethod
    def delete(self, key):
        pass

    @abstractmethod
    def update(self, key, value):
        pass

    @abstractmethod
    def select(self, key):
        pass

    @abstractmethod
    def read(self):
        pass

    @abstractmethod
    def save(self):
        pass

    def init(self, data):
        pass


class JsonDictFile(JsonFileInterface):
    def __init__(self, patientId, topKey):
        self.fileDir=os.path.join(constants.patientBaseUrl, patientId)
        self.filePath = os.path.join(constants.patientBaseUrl, patientId, constants.projectFileName)
        self.topKey = topKey
        self.jsonAllData={}
        self.jsonData = {}

    def exec(self, method, key, value):
        if method == "init":
            os.mkdir(self.fileDir)
            self.init(value)
            self.save()
            return
            
        self.jsonAllData = self.read()
        if self.topKey in self.jsonAllData:
            self.jsonData = self.jsonAllData.get(self.topKey,{})

        if method == "insert":
            self.insert(key, value)
            self.save()
        elif method == "delete":
            self.delete(key)
            self.save()
        elif method == "update":
            self.update(key, value)
            self.save()
        elif method == "select":
            return self.select(key)
        

    def insert(self, key, value):
        self.jsonData[key] = value
        

    def delete(self, index):
        return self.jsonData.pop(index)

    def update(self, key, value):
        self.jsonData[key] = value

    def select(self, key):
        return self.jsonData[key]

    def read(self):
        with open(self.filePath, encoding='utf-8') as f:
            data = json.load(f)
        return data

    def save(self):
        self.jsonAllData[self.topKey] = self.jsonData
        newJsonDict = json.dumps(self.jsonAllData)
        fh = open(self.filePath, 'w', encoding='utf-8')
        fh.write(newJsonDict)
        fh.close()
        

    def init(self, data):
        self.jsonAllData={
    "patientInformation": {
        
    },
    "stlFiles": [
        
    ],
    "points": [

    ],
    "information":{
        
    }
}
        self.jsonData = data


class JsonListFile(JsonFileInterface):
    def __init__(self, patientId, topKey):
        self.filePath = os.path.join(constants.patientBaseUrl, patientId, constants.projectFileName)
        self.topKey = topKey
        self.jsonAllData = self.read()
        self.jsonData = self.jsonAllData.get(self.topKey,[])

    def exec(self, method, index, value):
        if method == "insert":
            self.insert(value)
            self.save()
        elif method == "delete":
            self.delete(index)
            self.save()
        elif method == "update":
            self.update(index, value)
            self.save()
        elif method == "select":
            return self.select(index)

    def insert(self, value):
        self.jsonData.append(value)

    def delete(self, index):
        self.jsonData.pop(index)

    def update(self, index, value):
        if (type(value)==str):
            value = json.loads(value)
        for key, keyValue in value.items():
            self.jsonData[index][key] = keyValue

    def select(self, index):
        return self.jsonData[index]

    def read(self):
        with open(self.filePath, encoding='utf-8') as f:
            data = json.load(f)
        return data

    def save(self):
        self.jsonAllData[self.topKey] = self.jsonData
        newJsonDict = json.dumps(self.jsonAllData)
        fh = open(self.filePath, 'w', encoding='utf-8')
        fh.write(newJsonDict)
        fh.close()
